// 对象工具

/**
 * 深拷贝
 * @param obj 对象
 */
export const deepClone = <T>(obj: T): T => {
  if (obj === null || typeof obj !== 'object') return obj;

  if (obj instanceof Date) return new Date(obj) as any;
  if (obj instanceof RegExp) return new RegExp(obj) as any;

  const clone = Array.isArray(obj) ? [] : {};

  Object.keys(obj).forEach((key) => {
    clone[key] = deepClone(obj[key]);
  });

  return clone as T;
};

/**
 * 对象合并
 * @param target 目标对象
 * @param source 源对象
 */
export const merge = <T extends object, U extends object>(target: T, source: U): T & U => {
  const result = { ...target } as T & U;

  Object.keys(source).forEach((key) => {
    const sourceValue = source[key];
    if (sourceValue === undefined) return;
    if (sourceValue === null) {
      result[key] = null;
      return;
    }
    if (typeof sourceValue === 'object') {
      if (typeof result[key] === 'object') {
        result[key] = merge(result[key], sourceValue);
        return;
      }
    }
    result[key] = sourceValue;
  });

  return result;
};

/**
 * 对象过滤
 * @param obj 对象
 * @param predicate 过滤函数
 */
export const filterObject = <T extends object>(obj: T, predicate: (value: T[keyof T], key: keyof T) => boolean): Partial<T> => {
  return Object.keys(obj).reduce((acc, key) => {
    const k = key as keyof T;
    if (predicate(obj[k], k)) {
      acc[k] = obj[k];
    }
    return acc;
  }, {} as Partial<T>);
};

/**
 * 对象转查询字符串
 * @param obj 对象
 */
export const toQueryString = (obj: Record<string, any>): string => {
  return Object.entries(obj)
    .filter(([_, value]) => value !== undefined && value !== null)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
    .join('&');
};
